from flask_wtf import FlaskForm
from marshmallow import fields, pre_dump, Schema
from wtforms import StringField
from wtforms.validators import DataRequired, Length, URL
from wtforms.validators import Optional

from pkg.pageinator import PaginatorReq
from .schema import ListField
from ..exception import ValidateErrorException
from ..model import ApiToolProvider, ApiTool


class ApiToolSchema(FlaskForm):
    openapi_schema = StringField(
        "openapi_schema",
        validators=[
            DataRequired(message="openapi_schema不能为空")
        ],
    )


class GetApiToolProvidersWithPageReq(PaginatorReq):
    search_word = StringField("search_word", validators=[
        Optional()
    ])


class CreateApiToolSchema(FlaskForm):
    name = StringField(
        "name",
        validators=[
            DataRequired(message="name不能为空"),
            Length(min=1, max=30, message="名字长度不能超过30个字符")
        ]
    )
    headers = ListField("headers")

    @classmethod
    def validate_header(cls, form, fild):
        for header in fild.data:
            if not isinstance(header, dict):
                raise ValidateErrorException(message="header里的每一个元素必须为字典")
            if set(header.keys()) != {"key", "value"}:
                raise ValidateErrorException("headers里的每一个元素都必须包含key/value两个属性，不允许有其他属性")

    icon = StringField(
        "icon",
        validators=[
            DataRequired(message="icon不能为空"),
            URL(message="icon格式必须为url")
        ]
    )
    openapi_schema = StringField(
        "openapi_schema",
        validators=[
            DataRequired(message="openapi_schema不能为空")
        ],
    )


class ProviderRsp(Schema):
    """获取API工具提供者响应信息"""
    id = fields.UUID()
    name = fields.String()
    icon = fields.String()
    openapi_schema = fields.String()
    headers = fields.List(fields.Dict, default=[])
    created_at = fields.Integer(default=0)

    @pre_dump
    def process_data(self, data: ApiToolProvider, **kwargs):
        return {
            "id": data.id,
            "name": data.name,
            "icon": data.icon,
            "openapi_schema": data.openapi_schema,
            "headers": data.headers,
            "created_at": int(data.created_at.timestamp()),
        }


class ToolsRsp(Schema):
    """获取API工具响应信息"""
    id = fields.UUID()
    name = fields.String()
    description = fields.String()
    inputs = fields.List(fields.Dict, default=[])
    provider = fields.Dict()

    @pre_dump
    def process_data(self, data: ApiTool, **kwargs):
        provider = data.provider
        print(provider)
        return {
            "id": data.id,
            "name": data.name,
            "description": data.description,
            "inputs": [{k: v for k, v in item.items() if k != "in"} for item in data.parameters],
            "provider": {
                "id": provider.id,
                "name": provider.name,
                "icon": provider.icon,
                "openapi_schema": provider.openapi_schema,
                "headers": provider.headers,
            },
            "created_at": int(data.created_at.timestamp()),
        }


class GetApiToolProvidersWithPageResp(Schema):
    id = fields.UUID()
    name = fields.String()
    icon = fields.String()
    description = fields.String()
    openapi_schema = fields.String()
    headers = fields.List(fields.Dict, default=[])
    created_at = fields.Integer(default=0)
    tools = fields.List(fields.Dict(), default=[])

    @pre_dump
    def process_data(self, data: ApiToolProvider, **kwargs):
        tools = data.get_tools
        return {
            "id": data.id,
            "name": data.name,
            "icon": data.icon,
            "openapi_schema": data.openapi_schema,
            "description": data.description,
            "headers": data.headers,
            "tools": [{
                "id": t.id,
                "name": t.name,
                "description": t.description,
                "inputs": [{k: v for k, v in item.items() if k != "in"} for item in t.parameters],
            } for t in tools],
            "created_at": int(data.created_at.timestamp()),
        }
